home *** CD-ROM | disk | FTP | other *** search
/ Maclife 157 / MACLIFE157-2001-09.ISO.7z / MACLIFE157-2001-09.ISO / Linux / MacOS Tools / Other / BootX 1.1.3 (for Old Mac OS) / Sources / src / DeviceTree.c < prev    next >
C/C++ Source or Header  |  2001-07-23  |  7KB  |  279 lines

  1. #include <MacTypes.h>
  2.  
  3. #include <stdlib.h>
  4. #include <string.h>
  5.  
  6. #include "DeviceTree.h"
  7.  
  8. // Globals
  9. int device_tree_skip_macos            = 1;
  10. int device_tree_max_prop_length        = 1024;
  11.  
  12. // Statics
  13. static RegEntryID                    gEntryID;
  14. static struct device_node*            gAllNodes;
  15. static struct device_node**            gAllNextP;
  16. static Ptr                            gRegistryBase;
  17.  
  18. static char*                        gCurRegPath;
  19.  
  20. // Prototypes
  21. static Ptr                inspect_node(     struct device_node *dad, Ptr where );
  22. static unsigned char *    get_property(     struct device_node *np, const char *name, unsigned long *lenp);
  23. static void                relocate_node(    struct device_node *np);
  24.  
  25. // Macros
  26. #define ALIGN(x) (((x) + sizeof(unsigned long)-1) & -sizeof(unsigned long))
  27. #define RELOC(x) ((x) ? (((Ptr)(x)) - gRegistryBase) : NULL)
  28.  
  29. // Exported copy_device_tree routine
  30. OSStatus
  31. copy_device_tree(Ptr where, unsigned long *size, unsigned long *outMainDispOffset)
  32. {
  33.     OSStatus        err;
  34.     Boolean            done = false;
  35.     Ptr                end;
  36.     GDHandle        mainDisplay;
  37.     AuxDCEHandle    mainDispDCE;
  38.     
  39.     /// By default, we don't know which one is the main display
  40.     *outMainDispOffset = 0;
  41.     
  42.     // We get the device control entry of the main display
  43.     mainDisplay = GetMainDevice();
  44.     mainDispDCE = (AuxDCEHandle)GetDCtlEntry((**mainDisplay).gdRefNum);
  45.     
  46.     // We get the root of the device tree inside the registry
  47.     err = RegistryEntryIDInit(&gEntryID);
  48.     if (err == noErr)
  49.         err = RegistryCStrEntryLookup(NULL, "Devices:device-tree", &gEntryID);
  50.     if (err != noErr)
  51.         return err;
  52.  
  53.     if ((err == noErr) && !done)
  54.     {
  55.         struct device_node*    node;
  56.         struct device_node*    next_node;
  57.         
  58.         // Iterate the registry & copy everything
  59.         gCurRegPath = NULL;        
  60.         gRegistryBase = where;
  61.         *((long *)where) = 0;
  62.         where += 4;
  63.         gAllNextP = &gAllNodes;
  64.         end = inspect_node(NULL, where);
  65.         *gAllNextP = 0;
  66.         *size = end - where;
  67. // -- This one gives an error with Spotlight. I still have to check if it's a real
  68. //    error or not, but in the meantime, let's disable it.
  69. //        RegistryEntryIDDispose(&gEntryID);
  70.         
  71.         // Now, relocate it
  72.         node = gAllNodes;
  73.         while(node)
  74.         {
  75.             unsigned char*    did;
  76.             unsigned long    didLength;
  77.             
  78.             // Get next node pointer before it is relocated
  79.             next_node = node->allnext;
  80.             
  81.             // Check if this node is a display device and contains the magic "did" property
  82.             if (strcmp(node->type, "display") == 0)
  83.             {
  84.                 did = get_property(node, "did", &didLength);
  85.                 if (did && didLength == sizeof(unsigned long))
  86.                     if (*((unsigned long *)did) == (**mainDispDCE).dCtlSlot)
  87.                         *outMainDispOffset = (unsigned long)RELOC(node);
  88.             }
  89.             
  90.             // Relocate the node        
  91.             relocate_node(node);
  92.             
  93.             // Go to next node
  94.             node = next_node;
  95.         }
  96.     } else
  97.         *size = 0;
  98.     
  99.     return err;
  100. }
  101.  
  102. // Internel inspect_node recursive routine
  103. Ptr
  104. inspect_node( struct device_node *dad, Ptr where )
  105. {
  106.     OSStatus            err = noErr;
  107. //    unsigned long        l;
  108.     struct device_node    *np;
  109.     struct property        *pp, **prev_propp;
  110.     RegPropertyIter        propIter;
  111.     Boolean                done = false;
  112.     RegEntryID            me;
  113.     RegEntryIter        cookie;
  114.     char*                saveRegPath = gCurRegPath;
  115.  
  116.     np = ( struct device_node * ) where;
  117.     where += sizeof( struct device_node );
  118.     memset(np, 0, sizeof(struct device_node));
  119.     
  120. //    np->node = node;
  121.     *gAllNextP = np;
  122.     gAllNextP = &np->allnext;
  123.     np->parent = dad;
  124.     if ( dad )
  125.     {
  126.         /* we temporarily use the `next' field as `last_child'. */
  127.         if (dad->next == 0)
  128.             dad->child = np;
  129.         else
  130.             dad->next->sibling = np;
  131.         dad->next = np;
  132.     }
  133.  
  134.     /* get and store all properties */
  135.     prev_propp = &np->properties;
  136.     
  137.     err = RegistryPropertyIterateCreate( &gEntryID, &propIter );
  138.     
  139.     for (;;) {
  140.         pp = (struct property *) where;
  141.         pp->name = ( char * )( pp + 1 );
  142.         
  143.         err = RegistryPropertyIterate( &propIter, (RegPropertyName *)pp->name, &done);
  144.         if ( err || done )
  145.             break;
  146.         
  147.         // Skip MacOS driver property
  148.         if (device_tree_skip_macos && (strcmp(pp->name, "driver,AAPL,MacOS,PowerPC") == 0))
  149.             continue;
  150.  
  151.         err = RegistryPropertyGetSize( &gEntryID, pp->name, ( unsigned long * )( &pp->length ) );
  152.         if (err != noErr)
  153.             continue;
  154.     
  155.         // Should not happen, but...
  156.         if (pp->length < 0)
  157.             continue;
  158.         
  159.         // Skip too large properties
  160.         if (device_tree_max_prop_length && (pp->length > device_tree_max_prop_length))
  161.             continue;
  162.  
  163.         where = ( Ptr )ALIGN( ( unsigned long )pp->name + strlen( pp->name ) + 1 );
  164.         pp->value = ( unsigned char * ) where;
  165.         pp->length = -1;
  166.         err = RegistryPropertyGet( &gEntryID, pp->name, pp->value, ( unsigned long * )( &pp->length ) );
  167.         where = ( Ptr )ALIGN( ( unsigned long ) where + pp->length );
  168.  
  169.         *prev_propp = pp;
  170.         prev_propp = &pp->next;
  171.     }
  172.     
  173.     done = false;
  174.     err = RegistryPropertyIterateDispose( &propIter );
  175.     *prev_propp = 0;
  176.  
  177.     np->name = ( char * )get_property(np, "name", 0);
  178.     np->type = ( char * )get_property(np, "device_type", 0);
  179.  
  180.     /* get the node's full name */
  181.     np->full_name = ( char * ) where;
  182.     if (gCurRegPath == NULL)
  183.         strcpy(np->full_name, "/");
  184.     else
  185.     {
  186.         strcpy(np->full_name, gCurRegPath);
  187.         if (strlen(gCurRegPath) > 1)
  188.             strcat(np->full_name, "/");
  189.         strcat(np->full_name, np->name);
  190.     }
  191.     gCurRegPath = np->full_name;
  192.     where = ( Ptr )ALIGN( ( unsigned long ) where + strlen(np->full_name) + 1 );
  193.  
  194.     /* Backup entry to me */
  195.     err = RegistryEntryIDInit(&me);
  196.     if (err != noErr)
  197.         return where;
  198.     
  199.     err = RegistryEntryIDCopy(&gEntryID, &me);
  200.     if (err != noErr)
  201.         return where;
  202.  
  203.     /* Iterate child nodes */
  204.     err = RegistryEntryIterateCreate(&cookie);
  205.     if (err == noErr)
  206.         err = RegistryEntryIterateSet(&cookie, &gEntryID);
  207.     if (err == noErr)
  208.     {
  209.         err = RegistryEntryIterate( &cookie, kRegIterChildren, &gEntryID, &done);
  210.  
  211.         while ((err == noErr) && !done)
  212.         {
  213.             where = inspect_node( np, where );
  214.             
  215.             err = RegistryEntryIterate( &cookie, kRegIterContinue, &gEntryID, &done );
  216.         }
  217.  
  218.         RegistryEntryIterateDispose(&cookie);
  219.     }
  220.     
  221.     // we got done, so we must reset the gEntryID
  222.     err = RegistryEntryIDCopy(&me, &gEntryID);
  223.     if (err != noErr)
  224.         return where;
  225.  
  226.     RegistryEntryIDDispose(&me);
  227.     
  228.     gCurRegPath = saveRegPath;
  229.     
  230.     return where;
  231. }
  232.  
  233. unsigned char *
  234. get_property( struct device_node *np, const char *name, unsigned long *lenp)
  235. {
  236.     struct property *pp;
  237.  
  238.     for ( pp = np->properties; pp != 0; pp = pp->next )
  239.         if ( strcmp( pp->name, (char *)name ) == 0 ) {
  240.             if ( lenp != 0 )
  241.                 *lenp = pp->length;
  242.             return pp->value;
  243.         }
  244.     return nil;
  245. }
  246.  
  247. void
  248. relocate_node(struct device_node *np)
  249. {
  250.     struct property*    prop;
  251.     struct property*    prop_next;
  252.     
  253.     prop = np->properties;
  254.     
  255.     np->name        = (char *)RELOC(np->name);
  256.     np->type        = (char *)RELOC(np->type);
  257.     np->node        = NULL;
  258.     np->addrs        = NULL;
  259.     np->full_name    = (char *)RELOC(np->full_name);
  260.     np->properties    = (struct property *)RELOC(np->properties);
  261.     np->parent        = (struct device_node *)RELOC(np->parent);
  262.     np->child        = (struct device_node *)RELOC(np->child);
  263.     np->sibling        = (struct device_node *)RELOC(np->sibling);
  264.     np->next        = (struct device_node *)RELOC(np->next);
  265.     np->allnext        = (struct device_node *)RELOC(np->allnext);
  266.     
  267.     while(prop)
  268.     {
  269.         prop_next = prop->next;
  270.         
  271.         prop->name    = (char *)RELOC(prop->name);
  272.         prop->value    = (unsigned char *)RELOC(prop->value);
  273.         prop->next    = (struct property *)RELOC(prop->next);
  274.         
  275.         prop = prop_next;
  276.     }
  277. }
  278.  
  279.